/*
 * ***********************************************************
 * @Project: SCVHDemo
 * @File: SurfaceHostManager.java
 * @LastEditTime: 2024/11/17 15:07:42
 * @Author: chadm
 * ***********************************************************
 */

package com.example.host;

import static com.example.ipclibrary.MessageUtil.KEY_CLIENT_PACKAGE;
import static com.example.ipclibrary.MessageUtil.KEY_SURFACE_PACKAGE;
import static com.example.ipclibrary.MessageUtil.MSG_REC_SUBPACKAGE;
import static com.example.ipclibrary.MessageUtil.MSG_REG_CLIENT;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceView;

import androidx.annotation.NonNull;

import com.example.ipclibrary.MessageUtil;

import java.util.HashMap;

public class SurfaceHostManager {
    @SuppressLint("StaticFieldLeak")
    private static SurfaceHostManager sInstance;
    final String TAG = SurfaceHostManager.class.getSimpleName();
    private final HashMap<String,ClientInfo> mClients = new HashMap<>();
    private final Messenger mServiceMessenger;

    // 依赖注入，使用SurfaceView来显示不同的client view
    private SurfaceView mSurface;
    // 记录当前的client，以package name来区分
    private String mCurClient;

    public static SurfaceHostManager getInstance() {
        if(sInstance == null) {
            synchronized (SurfaceHostManager.class) {
                sInstance = new SurfaceHostManager();
            }
        }
        return sInstance;
    }

    private SurfaceHostManager() {
        mServiceMessenger = new Messenger(new MyHandler(Looper.getMainLooper()));
    }

    /**
     * 注入SurfaceView，client的view都显示在这个SurfaceView上面
     *
     * @param surfaceView 一个SurfaceView
     */
    public void initSurfaceView(SurfaceView surfaceView) {
        Log.i(TAG,"initSurfaceView");
        mSurface = surfaceView;
    }

    public Messenger getServiceMessenger() {
        return mServiceMessenger;
    }

    /**
     * 把touch事件分发给对应的client处理
     *
     * @param event touch事件
     */
    public void sendTouchToClient(MotionEvent event) {
        Log.i(TAG,"sendTouchToClient:" + mCurClient);
        Message msg = MessageUtil.obtainTouchEvent(event);
        sendMessageToClient(mCurClient,msg);
    }

    /**
     * 切换显示不同的client
     *
     * @param client 对应的client package name
     */
    public void changeShowView(String client) {
        Log.i(TAG,"changeShowView:" + client);
        mCurClient = client;
        sendSurfaceInfoToClient(mCurClient);
    }

    class MyHandler extends Handler {
        public MyHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            Log.i(TAG,"handleMessage: " + msg.what);
            switch (msg.what) {
                case MSG_REG_CLIENT:
                    handleClientReg(msg);
                    break;
                case MSG_REC_SUBPACKAGE:
                    handleClientSurfacePkg(msg);
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    private void sendSurfaceInfoToClient(String client) {
        Log.i(TAG,"sendSurfaceInfoToClient " + client);
        if(mSurface != null) {
            Message msg = MessageUtil.obtainSurfaceInfo(mSurface.getHostToken(),
                    mSurface.getDisplay().getDisplayId(),
                    mSurface.getWidth(),
                    mSurface.getHeight());
            sendMessageToClient(client,msg);
        } else {
            Log.e(TAG,"should call initSurfaceView first");
        }
    }

    private void sendMessageToClient(String client, Message msg) {
        Log.i(TAG,"sendMessageToClient: " + client);
        ClientInfo clientInfo = mClients.get(client);
        if(clientInfo != null) {
            Messenger messenger = clientInfo.mClientMessenger;
            if(messenger != null) {
                try {
                    messenger.send(msg);
                } catch (RemoteException e) {
                    Log.e(TAG,e.toString());
                }
            }
        } else {
            Log.w(TAG,"should register client first");
        }
    }

    private void handleClientSurfacePkg(Message msg) {
        Bundle bundle = msg.getData();
        SurfaceControlViewHost.SurfacePackage surfacePackage = bundle.getParcelable(KEY_SURFACE_PACKAGE);
        String appName = bundle.getString(KEY_CLIENT_PACKAGE);
        Log.i(TAG,"handleClientSurfacePkg: " + appName);

        ClientInfo clientInfo = mClients.get(appName);
        assert clientInfo != null;
        clientInfo.mSurfacePkg = surfacePackage;
        if(mSurface != null) {
            assert surfacePackage != null;
            // 看setChildSurfacePackage方法里面的实现，每次设置一个，老的那个就会被release掉
            mSurface.setChildSurfacePackage(surfacePackage);
        }
    }

    private void handleClientReg(Message msg) {
        Bundle bundle = msg.getData();
        String pkg = bundle.getString(KEY_CLIENT_PACKAGE);
        Log.i(TAG,"handleClientReg: " + pkg);

        ClientInfo clientInfo = mClients.get(pkg);
        if(clientInfo == null) {
            clientInfo = new ClientInfo();
            clientInfo.mClientMessenger = msg.replyTo;
            mClients.put(pkg,clientInfo);
            Log.d(TAG,"register client success");
        } else {
            clientInfo.mClientMessenger = msg.replyTo;
            Log.d(TAG,"update client info");
        }
    }

    static class ClientInfo {
        public Messenger mClientMessenger;
        public SurfaceControlViewHost.SurfacePackage mSurfacePkg;
    }
}
